import java.io.OutputStream;

/**
 * Classe MaP : Classe d'écriture en Yaka
 * 
 * @author BlobbyCompiloTeam
 * 
 */
public class MaP {

	protected OutputStream out; // Flux de sortie
	
	/**
	 * Constructeur
	 * @param str Chemin du fichier de sortie
	 */
	public MaP(String str) {
		out = Ecriture.ouvrir(str);
	}
	
	/**
	 * Ecrit l'en-tête du programme
	 */
	public void entete(){
		Ecriture.ecrireStringln(out, "entete");
	}
	
	/**
	 * Fonction non utilisé maintenant. Voir fonc_ouv_bloc.
	 * @param taille Taille des variables locales à ce bloc
	 */
	public void ouvprinc(int taille){
		Ecriture.ecrireStringln(out, "ouvprinc " + taille);
	}
	
	/**
	 * Ecrit la queue du programme
	 */
	public void queue(){
		Ecriture.ecrireStringln(out, "queue");
	}
	
	/**
	 * Indique la fin du programme. Retourne au système.
	 */
	public void retourSyst(){
		Ecriture.ecrireStringln(out,"retour au systeme");
	}

	/**
	 * Ecrit le début du programme principal
	 */
	public void etiq_princ() {
		Ecriture.ecrireStringln(out,"princ:");
	}
	
	/**
	 * Ecrit la fin du programme principal
	 */
	public void etiq_fprinc() {
		Ecriture.ecrireStringln(out,"fprinc:");
	}
	
	/**
	 * Fonction de passage à la ligne
	 */
	public void a_la_ligne(){
		Ecriture.ecrireStringln(out, "a_la_ligne");
	}
	
	/**
	 * Lit l'entier situé à l'offset passé en paramètre
	 * @param offset Offset de l'entier à lire
	 */
	public void lire_ent(int offset){
		Ecriture.ecrireStringln(out, "lire_ent " + offset);
	}
	
	/**
	 * Ecrit un entier
	 */
	public void ecrire_ent(){
		Ecriture.ecrireStringln(out, "ecrire_ent");
	}
	
	/**
	 * Ecrit un booléen
	 */
	public void ecrire_bool(){
		Ecriture.ecrireStringln(out, "ecrire_bool");
	}
	
	/**
	 * Ecrit une chaîne de caractères
	 * @param chaine Chaine de caractères à écrire
	 * @param nbChaine Numéro de la chaine.
	 */
	public void ecrire_chaine(String chaine, int nbChaine){
		Ecriture.ecrireStringln(out, "ecrire_chaine " + chaine);
	}
	
	/**
	 * Affecte la valeur située en tête de pile à la variable située à l'offset passé en paramètre
	 * @param offset Offset de la variable affectée
	 */
	public void aff_var(int offset){
		Ecriture.ecrireStringln(out, "aff_var " + offset);
	}
	
	/**
	 * Empile la valeur passée en paramètre
	 * @param val Valeur à empiler
	 */
	public void emp_val(int val) {
		Ecriture.ecrireStringln(out, "emp_val " + val);
	}
	
	/**
	 * Empile la variable située à l'offset passé en paramètre
	 * @param offset Offset de la variable à empiler
	 */
	public void emp_var(int offset) {
		Ecriture.ecrireStringln(out, "emp_var " + offset);
	}
	
	/**
	 * Opérateur pour l'addition. Additionne les deux valeurs situées en tête de pile.
	 */
	public void add() {
		Ecriture.ecrireStringln(out, "add");
	}
	
	/**
	 * Opérateur pour la soustraction. Soustrait les deux valeurs situées en tête de pile.
	 */
	public void sous() {
		Ecriture.ecrireStringln(out, "sous");
	}
	
	/**
	 * Opérateur pour la multiplication. Multiplie les deux valeurs situées en tête de pile.
	 */
	public void mul() {
		Ecriture.ecrireStringln(out, "mul");
	}
	
	/**
	 * Opérateur pour la division. Divise les deux valeurs situées en tête de pile.
	 */
	public void div() {
		Ecriture.ecrireStringln(out, "div");
	}
	
	/**
	 * Opérateur pour le ou logique. Réalise un ou logique sur les deux valeurs situées en tête de pile.
	 */
	public void ou() {
		Ecriture.ecrireStringln(out, "ou");
	}
	
	/**
	 * Opérateur pour le et logique. Réalise un et logique sur les deux valeurs situées en tête de pile.
	 */
	public void et() {
		Ecriture.ecrireStringln(out, "et");
	}
	
	/**
	 * Opérateur de comparaison strictement inférieur. Compare les deux valeurs situées en tête de pile.
	 */
	public void inf() {
		Ecriture.ecrireStringln(out, "inf");
	}
	
	/**
	 * Opérateur de comparaison inférieur ou égal. Compare les deux valeurs situées en tête de pile.
	 */
	public void infeq() {
		Ecriture.ecrireStringln(out, "infeq");
	}
	
	/**
	 * Opérateur de comparaison strictement supérieur. Compare les deux valeurs situées en tête de pile.
	 */
	public void sup() {
		Ecriture.ecrireStringln(out, "sup");
	}
	
	/**
	 * Opérateur de comparaison supérieur ou égal. Compare les deux valeurs situées en tête de pile.
	 */
	public void supeq() {
		Ecriture.ecrireStringln(out, "supeq");
	}
	
	/**
	 * Opérateur de comparaison d'égalité. Compare les deux valeurs situées en tête de pile.
	 */
	public void eq() {
		Ecriture.ecrireStringln(out, "eq");
	}
	
	/**
	 * Opérateur de comparaison de non égalité. Compare les deux valeurs situées en tête de pile.
	 */
	public void neq() {
		Ecriture.ecrireStringln(out, "neq");
	}
	
	/**
	 * Opérateur non logique. Inverse la valeur booléenne située en tête de pile.
	 */
	public void non() {
		Ecriture.ecrireStringln(out, "non");
	}
	
	/**
	 * Opérateur de négation. Inverse la valeure entière située en tête de pile.
	 */
	public void moins() {
		Ecriture.ecrireStringln(out, "moins");
	}
	
	/**
	 * Ferme le flux de sortie.
	 */
	public void fermer() {
		Ecriture.fermer(out);
	}

	/**
	 * Déclare le début d'une boucle tantque.
	 * @param numIter Numéro de la boucle pour l'étiquette
	 */
	public void iter_ttq(int numIter) {
		Ecriture.ecrireStringln(out, "ttq" + numIter + ":");
	}
	
	/**
	 * Déclare la condition d'arrêt d'une boucle tantque. 
	 * @param numIter Numéro de la boucle pour l'étiquette de fin d'itération
	 */
	public void iter_faire(int numIter) {
		Ecriture.ecrireStringln(out, "bsifaux fait" + numIter);
	}

	/**
	 * Permet un nouveau passage dans la boucle. 
	 * @param numIter Numéro de la boucle pour l'étiquette de saut
	 */
	public void iter_fait(int numIter) {
		Ecriture.ecrireStringln(out, "bincond ttq" + numIter + "\n" +
				"fait" + numIter + ":");
	}
	
	/**
	 * Déclare une nouvelle conditionnelle. 
	 * @param numCond Numéro de la conditionnelle pour l'étiquette.
	 */
	public void cond_si(int numCond)
	{
		Ecriture.ecrireStringln(out, "bsifaux aut" + numCond);
	}
	
	/**
	 * Permet la sortie de la conditionnelle. Evite d'entrer dans un sinon s'il n'existe pas
	 * @param numCond Numéro de la conditionnelle pour l'étiquette.
	 */
	public void cond_sinon(int numCond)
	{
		Ecriture.ecrireStringln(out, 	"bincond fsi" + numCond + "\n"
									+	"aut" + numCond + ":");
	}
	
	/**
	 * Déclare la fin d'une conditionnelle.
	 * @param numCond Numéro de la conditionnelle pour l'étiquette.
	 */
	public void cond_fsi(int numCond)
	{
		Ecriture.ecrireStringln(out,	"fsi" + numCond + ":");
	}
	
	/**
	 * Déclaration d'une nouvelle fonction. 
	 * @param nom Nom de la fonction.
	 */
	public void fonc_nom(String nom) {
		Ecriture.ecrireStringln(out, nom + ":");
	}
	
	/**
	 * Déclare la taille des variables locales dans le bloc.
	 * @param num Taille des variables locales au bloc.
	 */
	public void fonc_ouv_bloc(int num) {
		Ecriture.ecrireStringln(out, "ouv_bloc " + num);
	}
	
	/**
	 * Fin d'une fonction.
	 * @param nom Nom de la fonction
	 */
	public void fin_bloc(String nom){
		Ecriture.ecrireStringln(out, "f" + nom + ":");
	}
	
	/**
	 * Récupère un paramètre de la fonction et l'empile.
	 * @param num Offset du paramètre
	 */
	public void fonc_emp_vparf(int num) {
		Ecriture.ecrireStringln(out, "emp_vparf " + num);
	}
	
	/**
	 * Déclare une valeur de retour de la fonction. Sort de la fonction.
	 * @param val Valeur à retournée
	 * @param nom Nom de la fonction pour l'étiquette
	 */
	public void fonc_retourneVal(int val , String nom) {
		Ecriture.ecrireStringln(out, "retourneVal " + val + "\n" + "bincond f" + nom);
	}
	
	/**
	 * Ferme un bloc de variables locales.
	 * @param num Taille du bloc supprimer
	 */
	public void fonc_ferme_bloc(int num) {
		Ecriture.ecrireStringln(out, "ferme_bloc " + num + "\n");
	}
	
	/**
	 * Réserve un emplacement dans la pile pour la valeur de retour d'une fonction.
	 */
	public void fonc_val_retour() {
		Ecriture.ecrireStringln(out, "val_retour");
	}
	
	/**
	 * Appelle une fonction.
	 * @param nom Nom de la fonction à appeler
	 */
	public void fonc_appel_proc(String nom) {
		Ecriture.ecrireStringln(out, "appel_proc " + nom);
	}
	
}
